#pragma once
#include "framework/sweety.h"
#include "components/3D/sweety_3D_Math.h"
#include "components/3D/sweety_3D_Sprite.h"
#include <string>
#include <vector>

namespace SW
{
	class SW_API SceneObj
	{
	public:
							SceneObj(SceneObj* parent = nullptr, Sprite* sprite = nullptr, const std::string& objName = "No Name");
		virtual				~SceneObj();

		virtual void		Update(float deltaTime);
		virtual void		Render();

		inline static void	EulerTrans(mat4& modelTrans, float yaw, float pitch, float roll)
		{
			modelTrans = rotate(modelTrans, roll, vec3(0.0f, 0.0f, 1.0f));
			modelTrans = rotate(modelTrans, pitch, vec3(1.0f, 0.0f, 0.0f));
			modelTrans = rotate(modelTrans, yaw, vec3(0.0f, 1.0f, 0.0f));
		}

		inline static void	EulerTrans(mat4& modelTrans, const float* rad)
		{
			EulerTrans(modelTrans, rad[0], rad[1], rad[2]);
		}

		inline static void	QuaternionRotate(mat4& modelTrans, const quat& qua)
		{
			vec3 axisTemp = axis(qua);
			float angleTemp = angle(qua);
			modelTrans = rotate(modelTrans, angleTemp, axisTemp);
		}

		void				PushChild(SceneObj* child);

		const vec3&			GetPosition() const;
		float				GetYaw() const;
		float				GetPitch() const;
		float				GetRoll() const;
		const Sprite*		GetSprite()const;
		Sprite*				GetSprite();
		bool				HasChild() const;

		void				SetPosition(const vec3& position);
		void				SetYaw(float yaw);
		void				SetPitch(float pitch);
		void				SetRoll(float roll);
		void				SetEulerAngle(float yaw, float pitch, float roll);
		void				SetEulerAngle(float* eulerAngle);

		void				Move(const vec3& vec);

		const vec3&			GetScale() const;
		void				SetScale(const vec3& scale);

		void				EulerRotate(float yaw, float pitch, float roll);
		void				EulerRotateYaw(float yaw);
		void				EulerRotatePitch(float pitch);
		void				EulerRotateRoll(float roll);

		const std::string&	GetObjName() const;
		const std::vector<SceneObj*> GetChildren() const;

	private:
		void				Clear();
		void				UpdateQuaternion();

	private:
		SceneObj*				m_ParentObj{ nullptr };
		Sprite*					m_Sprite{ nullptr };
		std::vector<SceneObj*>	m_ChildObj;

		vec3					m_Position;
		vec3					m_Scale;
		float					m_Yaw;
		float					m_Pitch;
		float					m_Roll;

		mat4					m_ModelTrans;
		quat					m_Qua;

		std::string				m_ObjName;
	};
}